<?php
/**
 * Roles class
 *
 * @version:	0.1
 * @package:	core
 * @author:		alex_ez
 * @created:	12 february 2010
 *
 * @copyright:	(c) 2010 alex <qfox@ya.ru> yaroshevich aka alex_ez. All rights reserved.
 */

class Roles
{
	/**
	 * Inner storage for roles
	 * @var array
	 */
	private $_roles = null;

	/**
	 * Constructs a roles object by string or array
	 * @param mixed $roles
	 */
	public function __construct( $roles )
	{
		$this ->_roles = $this ->parse( $roles );
	}
	
	/**
	 * Checks up for role in storage
	 * @param string $k A role
	 * @return boolean
	 */
	public function have( $r )
	{
		//fb::log( $this ->_roles, 'roles' );
		//fb::log( $r, 'search for role' );
		return in_array( $r, $this ->_roles );
	}
	
	/**
	 * Alias to have Checks up role in storage
	 * @param string $k A role
	 * @return boolean
	 */
	public function haveRole( $r ) { return $this ->have( $r ); }
	
	/**
	 * Alias to have Checks up role in storage
	 * @param string $k A role
	 * @return boolean
	 */
	public function __get( $k )
	{
		//fb::log( $k, 'roles::__get(k)' );
		return $this ->have( $k );
	}

	/**
	 * Checks up for any role in params contains in storage
	 * @return boolean
	 */
	public function haveAny( ) { $args = func_get_args( ); return call_user_func_array( array($this,'any'), $args ); }
	public function any( )
	{
		$args = func_get_args( );
		$arg = reset( $args );
		if( count($args)==1 && $this ->parsable($arg) )
		{
			if( is_string( $arg ) ) return call_user_func_array( array($this,'any'), $this ->parse( $arg ) );
			if( is_array( $arg ) ) return call_user_func_array( array($this,'any'), $arg );
			return false;
		}
		
		foreach( $args as $arg )
			if( $this ->have( $arg ) ) return true;
		
		return false;
	}

	/**
	 * Checks up for contains all roles in params in storage
	 * @return boolean
	 */
	public function haveEvery( ) { $args = func_get_args( ); return call_user_func_array( array($this,'every'), $args ); }
	public function every( )
	{
		$args = func_get_args( );
		if( count( $args ) == 1 && $this ->parsable($arg) )
		{
			$arg = reset( $args );
			if( is_string( $arg ) ) return call_user_func_array( array($this,'every'), $this ->parse( $arg ) );
			if( is_array( $arg ) ) return call_user_func_array( array($this,'every'), $arg );
			return false;
		}
		
		foreach( $args as $arg )
			if( !$this ->have( $arg ) ) return false;
		
		return true;
	}

	/**
	 * Check up for $roles consistency and determine parsable status
	 *
	 * @param mixed $roles
	 * @return boolean
	 */
	public function parsable( $roles )
	{
		if( is_array( $roles ) )
			return true;
		elseif( is_string( $roles ) )
			return strpos($roles,' ') || strpos($roles,',');
		
		return false;
	}

	/**
	 * Plain roles parse
	 *
	 * @param mixed $roles
	 * @return array
	 */
	public function parse( $roles )
	{
		if( is_array( $roles ) )
			$roles = array_values( $roles );
		elseif( is_string( $roles ) )
			$roles = array_filter( explode( ',', str_replace( ' ', ',', $roles ) ) );
		else
			$roles = array( );
		
		return $roles;
	}

	/**
	 * Roles filter. Cleans current roles with callback function
	 *
	 * @param callback $callback
	 * @return $this
	 */
	public function filter( $callback )
	{
		$this ->_roles = array_filter( $this ->_roles, $callback );
		return $this;
	}
	

	/**
	 * Gets current roles as array
	 * @return array
	 */
	public function toArray( )
	{
		return $this ->_roles;
	}
	
	/**
	 * Alias to __toString
	 * @return string
	 */
	public function toString( )
	{
		return $this ->__toString( );
	}

	/**
	 * Joins current roles to string
	 * @return string
	 */
	public function __toString( )
	{
		return join( ', ', $this ->_roles );
	}
}
